/*
 * @FileName: [MerchantServiceImpl.java]
 * 
 * @Package com.bcinfo.iccard.service.impl
 * 
 * 
 * Copyright (c) 2011-2015 BCINFO Technology Limited Com. All rights reserved.
 * 
 * This software is the confidential and proprietary information of BCINFO Technology Limited Company ("Confidential Information"). You shall not disclose such Confidential Information and shall use it only in accordance with the terms of the contract agreement you entered into with RKY.
 * 
 * $Rev$ $LastChangedDate$ $LastChangedBy$
 * 
 * @category ICCARD
 * 
 * @version 1.1
 * 
 * @author $Author$
 * 
 * Change History:[Formatter: author date description] <br/> 1 2 3
 */

package com.bcinfo.iccard.service.impl;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Service;

import com.bcinfo.iccard.dao.CheckReasonMapper;
import com.bcinfo.iccard.dao.DiscountMapper;
import com.bcinfo.iccard.dao.MerchantMapper;
import com.bcinfo.iccard.dao.PosMapper;
import com.bcinfo.iccard.exception.IccardDatabaseException;
import com.bcinfo.iccard.exception.InvalidParametersException;
import com.bcinfo.iccard.exception.MerchantEncodeHasBandByOtherException;
import com.bcinfo.iccard.model.CheckReason;
import com.bcinfo.iccard.model.Discount;
import com.bcinfo.iccard.model.Merchant;
import com.bcinfo.iccard.model.Pos;
import com.bcinfo.iccard.service.MerchantService;
import com.bcinfo.iccard.util.PaginationList;

/**
 * 一句话描述 <br/>
 * <p>
 * Description:<br/>
 * <p>
 * 
 * <p>
 * For Examples <br/>
 * 
 * <PRE>
 * </PRE>
 * <p>
 */
@Service
public class MerchantServiceImpl implements MerchantService
{
    @Autowired
    private MerchantMapper      _merchantMapper;
    @Autowired
    private CheckReasonMapper   _checkReasonMapper;
    @Autowired
    private DiscountMapper      _discountMapper;
    @Autowired
    private PosMapper           _posMapper;


    private static final Logger _logger = Logger.getLogger(MerchantServiceImpl.class);

    /*
     * (non-Javadoc) Description: <br/>
     * 
     * @param name
     * 
     * @param code
     * 
     * @return
     * 
     * @see com.bcinfo.iccard.service.MerchantService#findByNameCode(java.lang.String, java.lang.String)
     */
    @Override
    public List<Merchant> findByNameCode(String keyword, int maxRows)
    {
        if (StringUtils.isNotBlank(keyword))
            return _merchantMapper.selectByNameCode(keyword, maxRows);
        return new ArrayList<Merchant>();
    }

    /*
     * (non-Javadoc) Description: <br/>
     * 
     * @param merchantCode
     * 
     * @param merchantCheckStatus
     * 
     * @param merchantType
     * 
     * @param beginTime
     * 
     * @param endTime
     * 
     * @param pageSize
     * 
     * @param pageNo
     * 
     * @return
     * 
     * @see com.bcinfo.iccard.service.MerchantService#list(java.lang.String, int, java.lang.String, java.lang.String, java.lang.String, int, int)
     */
    @Override
    public PaginationList<Merchant> merchantList(String merchantEncode, int merchantCheckStatus, int merchantType,
            String beginTime, String endTime, int pageSize, int pageNo)
    {
        PaginationList<Merchant> paginationList = new PaginationList<Merchant>();
        List<Merchant> merchantLists = null;
        int totalLogCount = 0;
        if (_logger.isDebugEnabled())
        {
            _logger.debug("merchantList:merchantEncode=" + merchantEncode + ",merchantCheckStatus=" + merchantCheckStatus
                    + ",merchantType=" + merchantType + ",beginTime=" + beginTime + ",endTime = " + endTime
                    + ",pageSize=" + pageSize + ",pageNo=" + pageNo);
        }

        try
        {
            totalLogCount = _merchantMapper.selectCountByStatusAndType(merchantEncode, merchantCheckStatus, merchantType,
                    beginTime, endTime);
        }
        catch (Exception e)
        {
            _logger.error(ExceptionUtils.getStackTrace(e));
        }

        if (pageNo <= 0 || totalLogCount < (pageNo - 1) * pageSize || pageSize <= 0)
        {
            _logger.error("parameter is wrong");
        }

        int benginIndex = pageSize * pageNo - pageSize;

        try
        {
            merchantLists = _merchantMapper.selectByPage(merchantEncode, merchantCheckStatus, merchantType, beginTime,
                    endTime, benginIndex, pageSize);
        }
        catch (Exception e)
        {
            _logger.error(ExceptionUtils.getStackTrace(e));
        }

        int totalPage = totalLogCount % pageSize == 0 ? totalLogCount / pageSize : totalLogCount / pageSize + 1;

        paginationList.setTotalPage(totalPage);
        paginationList.setCurrPage(pageNo);
        paginationList.setPageSize(pageSize);
        paginationList.setRecords(merchantLists);
        paginationList.setTotalRecord(totalLogCount);

        return paginationList;
    }

    /*
     * (non-Javadoc) Description: <br/>
     * 
     * @return
     * 
     * @see com.bcinfo.iccard.service.MerchantService#findAll()
     */
    @Override
    public List<Merchant> findAll()
    {
        return _merchantMapper.selectAll();
    }

    /*
     * (non-Javadoc) Description: <br/>
     * 
     * @param merchant
     * 
     * @return
     * 
     * @see com.bcinfo.iccard.service.MerchantService#add(com.bcinfo.iccard.model.Merchant)
     */
    @Override
    public int add(Merchant merchant) throws MerchantEncodeHasBandByOtherException, IccardDatabaseException,
            MerchantNameIsExistException
    {
        if(merchant==null){
            return -1;
        }
        if (_logger.isDebugEnabled())
        {
            _logger.debug("merchant=" + merchant.toString());
        }
        int result=0;
        try
        {
            result=_merchantMapper.insertSelective(merchant);
            if(merchant.getPoslists()!=null && !merchant.getPoslists().isEmpty()){
                for (Pos pos : merchant.getPoslists())
                {
                    pos.setMerchantId(merchant.getMerchantId());
                    pos.setPosStatus(1);
                    _posMapper.insertSelective(pos);
                } 
            }
            //插入折扣信息
            Discount discount = new Discount();
            discount.setMerchantId(merchant.getMerchantId());
            discount.setRechargeableCardDiscountRate(merchant.getRechargeableCardDiscountRate());
            discount.setCreateTime(new Date());
            discount.setDiscountStatus(Short.valueOf("0"));//discount_status   1：正在使用    0：停止使用  ，审核通过之后才能使用
            _discountMapper.insertSelective(discount);
        }
        catch (DataAccessException _e)
        {
            _logger.error(ExceptionUtils.getStackTrace(_e));
            throw new IccardDatabaseException();
        }

        return result;
    }

    /*
     * (non-Javadoc) Description: <br/>
     * 
     * @param merchant
     * 
     * @return
     * 
     * @throws MerchantEncodeHasBandByOtherException
     * 
     * @throws IccardDatabaseException
     * 
     * @see com.bcinfo.iccard.service.MerchantService#update(com.bcinfo.iccard.model.Merchant)
     */
    @Override
    public int update(Merchant merchant) throws MerchantEncodeHasBandByOtherException, IccardDatabaseException,
            InvalidParametersException, MerchantNameIsExistException
    {
        if (merchant == null)
        {
            _logger.error("update parameter is wrong :merchant is null");
            throw new InvalidParametersException();
        }
        if (_logger.isDebugEnabled())
        {
            _logger.debug("merchant=" + merchant.toString());
        }
        try
        {
            int resultCount = _merchantMapper.updateByPrimaryKeySelective(merchant);

            if (_logger.isDebugEnabled())
            {
                _logger.debug("update:result update count is " + resultCount);
            }
            //update pos
            List<Pos> posListParam=merchant.getPoslists();
            if(posListParam!=null && !posListParam.isEmpty()){
                List<Pos> posList=_posMapper.findByMerchant(merchant.getMerchantId());
                Map<String,Pos> currentPos=transToMap(posList);
                if(currentPos!=null && !currentPos.isEmpty()){
                    for(Pos pos:posListParam){
                        //pos编码不存在
                        if(!currentPos.containsKey(pos.getPosCode()) ){
                            //没有posid表示新增pos
                            if(pos.getPosId()==null){
                                if (_logger.isDebugEnabled())
                                {
                                    _logger.debug(MessageFormat.format("add new pos for merchant{0},pos ={1}",merchant.getMerchantId(),pos.toString()));
                                }
                                pos.setPosStatus(1);
                                _posMapper.insertSelective(pos);
                            }else{
                                //有posid表示修改当前pos编码
                                if (_logger.isDebugEnabled())
                                {
                                    _logger.debug(MessageFormat.format("update pos for merchant{0},pos ={1}",merchant.getMerchantId(),pos.toString()));
                                }
                                _posMapper.updateByPrimaryKeySelective(pos);
                            }
                        }
                    }
                }else{
                    //没有POS，全部插入
                    for(Pos pos :posListParam){
                        _posMapper.insertSelective(pos);
                    }
                }
            }
            //update discount
            Integer discountRate=merchant.getRechargeableCardDiscountRate();
            if(discountRate!=null){
                Discount discount=_discountMapper.loadByMerchantAndDiscount(merchant.getMerchantId(), discountRate);
                //不存在，则插入新的折扣率
                if(discount==null){
                    discount=new Discount();
                    discount.setMerchantId(merchant.getMerchantId());
                    discount.setRechargeableCardDiscountRate(merchant.getRechargeableCardDiscountRate());
                    discount.setCreateTime(new Date());
                    //待审核
                    discount.setDiscountStatus(Short.valueOf("0"));//discount_status   1：正在使用    0：停止使用
                    discount.setRechargeableCardDiscountRate(discountRate);
                    _discountMapper.insertSelective(discount);
                }else{//存在
                    if(discount.getDiscountStatus() == 1)//正在使用，说明没有更改过折扣率
                    {
                        
                    }else if(discount.getDiscountStatus() == 0)//说明已存在的折扣率被重新启用
                    {
                        discount.setCreateTime(new Date());//更新为当前时间，便于审核时加载此记录
                        _discountMapper.updateByPrimaryKeySelective(discount);
                    }
                }
            }
            return resultCount;
        }
        catch (DataAccessException _e)
        {
            _logger.error(ExceptionUtils.getStackTrace(_e));
            throw new IccardDatabaseException();
        }

    }
    protected Map<String,Pos> transToMap(List<Pos> posList){
        if(posList!=null){
            Map<String,Pos> map=new HashMap<String,Pos>();
            for(Pos pos:posList){
                map.put(pos.getPosCode(), pos);
            }
            return map;
        }else{
            return null;
        }
    }

    /*
     * (non-Javadoc) Description: <br/>
     * 
     * @param merchantId
     * 
     * @return
     * 
     * @throws IccardDatabaseException
     * 
     * @see com.bcinfo.iccard.service.MerchantService#load(long)
     */
    @Override
    public Merchant load(long merchantId) throws IccardDatabaseException
    {
        if (_logger.isInfoEnabled())
        {
            _logger.info("load:merchantId=" + merchantId);
        }
        Merchant merchant = null;
        try
        {
            merchant = _merchantMapper.selectByPrimaryKey(merchantId);
            
            List<Pos> posList = _posMapper.findByMerchant(merchantId);
            
            merchant.setPoslists(posList);
            
            
        }
        catch (DataAccessException e)
        {
            _logger.error(ExceptionUtils.getStackTrace(e));
            throw new IccardDatabaseException();
        }
        if (merchant != null)
        {
            _logger.debug("load:result merchant=" + merchant.toString());
        }
        return merchant;
    }

    /*
     * (non-Javadoc) Description: <br/>
     * 
     * @param merchantId
     * 
     * @param status
     * 
     * @param msg
     * 
     * @param opId
     * 
     * @return
     * 
     * @throws IccardDatabaseException
     * 
     * @see com.bcinfo.iccard.service.MerchantService#audit(long, int, java.lang.String, long)
     */
    @Override
    public int audit(long merchantId, int status, String msg, long opId) throws IccardDatabaseException
    {
        if (_logger.isInfoEnabled())
        {
            _logger.info("audit:status=" + status + ",merchantId=" + merchantId + ",msg=" + msg + ",opId=" + opId);
        }
        try
        {
            Merchant merchant = new Merchant();
            merchant.setMerchantId(merchantId);
            merchant.setMerchantCheckStatus(status);
            if (status == 1)
            {
                merchant.setIsDelete(false);// 一旦审核通过后，就不可以删除 
            }
            int resultCount = _merchantMapper.updateByPrimaryKeySelective(merchant);

            CheckReason checkReason = new CheckReason();
            checkReason.setMerchantId(merchantId);
            checkReason.setUserId(opId);
            checkReason.setCheckContent(msg);

            _checkReasonMapper.insertSelective(checkReason);

            if (status == 1)
            {
                // 一旦审核通过后，先，停用此商家正在使用的折扣率，启用最新的折扣率
                
                List<Discount> discountList = _discountMapper.loadByMerchantId(merchantId);
                
                if(discountList != null && !discountList.isEmpty()){
                    for(Discount discount : discountList){
                        if(discount.getDiscountStatus() == 1){
                            discount.setDiscountStatus(Short.valueOf("0"));//discount_status   1：正在使用    0：停止使用
                            _discountMapper.updateByPrimaryKeySelective(discount);
                        }
                    }
                    
                    Discount dis = discountList.get(0);
                    dis.setDiscountStatus(Short.valueOf("1"));
                    _discountMapper.updateByPrimaryKeySelective(dis);
                    
                }
            }
            
            
            if (_logger.isDebugEnabled())
            {
                _logger.debug("audit:result audit count is " + resultCount);
            }
            return resultCount;
        }
        catch (DataAccessException e)
        {
            _logger.error(ExceptionUtils.getStackTrace(e));
            throw new IccardDatabaseException();
        }
    }

    /*
     * (non-Javadoc) Description: <br/>
     * 
     * @param status
     * 
     * @return
     * 
     * @throws IccardDatabaseException
     * 
     * @see com.bcinfo.iccard.service.MerchantService#setStatus(int)
     */
    @Override
    public boolean setStatus(Long merchantId, int merchantStatus) throws IccardDatabaseException,
            InvalidParametersException
    {
        if (_logger.isInfoEnabled())
        {
            _logger.info("setStatus:merchantStatus=" + merchantStatus);
        }
        if (merchantStatus < 0 || merchantStatus > 1)
        {
            _logger.error("setStatus:merchantStatus=" + merchantStatus + " is a innvalidParameter");
            throw new InvalidParametersException();
        }

        Merchant merchant = new Merchant();
        merchant.setMerchantId(merchantId);
        merchant.setMerchantStatus(merchantStatus);
    
        int result = 0;
        try
        {
            result = _merchantMapper.updateByPrimaryKeySelective(merchant);
        }
        catch (DataAccessException e)
        {
            _logger.error(ExceptionUtils.getStackTrace(e));
            throw new IccardDatabaseException();
        }
        if (result > 0)
        {
            if (_logger.isDebugEnabled())
            {
                _logger.debug("setStatus:merchantStatus=" + merchantStatus);
            }
            return true;
        }
        if (_logger.isDebugEnabled())
        {
            _logger.debug("setStatus:merchantStatus=" + merchantStatus);
        }
        return false;
    }

    /* (non-Javadoc)
     * Description: <br/> 
     *
     * @param merchantId
     * @return
     * @throws IccardDatabaseException 
     * @see com.bcinfo.iccard.service.MerchantService#loadRecentlyCheckReason(long)
     */
    @Override
    public CheckReason loadRecentlyCheckReason(long merchantId) throws IccardDatabaseException
    {
        if (_logger.isInfoEnabled())
        {
            _logger.info("loadRecentlyCheckReason:merchantId=" + merchantId);
        }
        CheckReason checkReason = null;
        try
        {
            checkReason = _checkReasonMapper.selectByMechantId(merchantId);
        }
        catch (DataAccessException e)
        {
            _logger.error(ExceptionUtils.getStackTrace(e));
            throw new IccardDatabaseException();
        }
        if (checkReason != null)
        {
            _logger.debug("loadComboCardCheckreason:result checkReason=" + checkReason.toString());
        }
        return checkReason;
    }

    /* (non-Javadoc)
     * Description: <br/> 
     *
     * @param merchantId
     * @return
     * @throws IccardDatabaseException 
     * @see com.bcinfo.iccard.service.MerchantService#delete(long)
     */
    @Override
    public int delete(long merchantId) throws IccardDatabaseException
    {
        int result = 0;
        if (_logger.isInfoEnabled())
        {
            _logger.info("delete:merchantId=" + merchantId);
        }
        
        try
        {
            _discountMapper.deleteByMerchantKey(merchantId);
            _posMapper.deleteByMerchantKey(merchantId);
            _checkReasonMapper.deleteByMerchantKey(merchantId);
        }
        catch (DataAccessException e)
        {
            _logger.error(ExceptionUtils.getStackTrace(e));
            throw new IccardDatabaseException();
        }
        try
        {
            result = _merchantMapper.deleteByPrimaryKey(merchantId);
        }
        catch (DataAccessException e)
        {
            _logger.error(ExceptionUtils.getStackTrace(e));
            throw new IccardDatabaseException();
        }
        return result;
    }

    @Override
    public int checkMerchantName(String merchantName) throws IccardDatabaseException
    {
        if (_logger.isDebugEnabled())
        {
            _logger.debug("checkMerchantName:merchantName=" + merchantName);
        }
        int count = 0;
        try
        {
            count = _merchantMapper.selectByMerchantName(merchantName);
        }
        catch (DataAccessException e1)
        {
            _logger.error(ExceptionUtils.getStackTrace(e1));
            throw new IccardDatabaseException();
        }
        return count;
    }
    @Override
    public int checkMerchantEncode(String merchantEncode) throws IccardDatabaseException
    {
        if (_logger.isDebugEnabled())
        {
            _logger.debug("checkMerchantEncode:merchantEncode=" + merchantEncode);
        }
        int count = 0;
        try
        {
            count = _merchantMapper.selectByMerchantEncode(merchantEncode);
        }
        catch (DataAccessException e1)
        {
            _logger.error(ExceptionUtils.getStackTrace(e1));
            throw new IccardDatabaseException();
        }
        return count;
    }

    /* (non-Javadoc)
     * Description: <br/> 
     *
     * @param merchantId
     * @return
     * @throws IccardDatabaseException 
     * @see com.bcinfo.iccard.service.MerchantService#loadAuditInfo(long)
     */
    @Override
    public Merchant loadAuditInfo(long merchantId) throws IccardDatabaseException
    {
        if (_logger.isInfoEnabled())
        {
            _logger.info("load:merchantId=" + merchantId);
        }
        Merchant merchant = null;
        try
        {
            merchant = _merchantMapper.selectByPrimaryKeyForAudit(merchantId);
            
            List<Pos> posList = _posMapper.findByMerchant(merchantId);
            merchant.setPoslists(posList);
        }
        catch (DataAccessException e)
        {
            _logger.error(ExceptionUtils.getStackTrace(e));
            throw new IccardDatabaseException();
        }
        if (merchant != null)
        {
            _logger.debug("load:result merchant=" + merchant.toString());
        }
        return merchant;
    }
    
}
